/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.mes.base.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.mes.base.entity.DictTreeNode;
import org.springblade.modules.mes.base.entity.MaterialInfo;
import org.springblade.modules.mes.base.entity.PrdBom;
import org.springblade.modules.mes.base.service.IMaterialInfoService;
import org.springblade.modules.mes.base.service.IPrdBomService;
import org.springblade.modules.mes.base.vo.MaterialInfoVO;
import org.springblade.modules.mes.opcua.constant.OpcUaCache;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 材料信息（材料库） 控制器
 *
 * @author BladeX
 * @since 2020-09-14
 */
@RestController
@AllArgsConstructor
@RequestMapping("/materialinfo")
@Api(value = "材料信息（材料库）", tags = "材料信息（材料库）接口")
public class MaterialInfoController extends BladeController {

	private final IMaterialInfoService materialInfoService;

	private IPrdBomService prdBomService;

	/**
	 * 详情
	 */
	@GetMapping("/detail")
	//@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入materialInfo")
	public R<MaterialInfo> detail(MaterialInfo materialInfo) {
		MaterialInfo detail = materialInfoService.getOne(Condition.getQueryWrapper(materialInfo));
		if (detail == null) {
			return R.fail("该材料不存在！");
		}
		return R.data(detail);
	}

	/**
	 * 不分页 材料信息（材料库）
	 */
	@GetMapping("/list")
	//@ApiOperationSupport(order = 2)
	@ApiOperation(value = "不分页", notes = "传入materialInfo")
	public R<List<MaterialInfoVO>> list(MaterialInfoVO materialInfo, Query query) {
		List<MaterialInfoVO> pages = materialInfoService.selectMaterialInfoList(materialInfo);
		return R.data(pages);
	}

	/**
	 * 获取所有物料
	 */
	@GetMapping("/materialList")
	@ApiOperation(value = "物料列表不分页", notes = "传入materialInfo")
	public R<List<MaterialInfoVO>> materialList(MaterialInfoVO materialInfo) {
		List<MaterialInfoVO> materialInfos = materialInfoService.materialList(materialInfo);
		return R.data(materialInfos);
	}

	/**
	 * 获取所有单价不为空物料
	 */
	@GetMapping("/materialLists")
	@ApiOperation(value = "物料列表不分页", notes = "传入materialInfo")
	public R<List<MaterialInfoVO>> materialLists(MaterialInfoVO materialInfo) {
		List<MaterialInfoVO> materialInfos = materialInfoService.getMaterialLists(materialInfo);
		List<MaterialInfoVO> materialInfosList = new ArrayList<>();
		for (MaterialInfoVO materialInfoVO : materialInfos) {
			if (materialInfoVO.getPrice() != null) {
				materialInfosList.add(materialInfoVO);
			}
		}
		return R.data(materialInfosList);
	}

	/**
	 * 根据材料名称模糊搜索原材料
	 * 只搜索材料状态不等于"7"-暂停的数据
	 */
	@GetMapping("/rawmateriallist")
	//@ApiOperationSupport(order = 2)
	@ApiOperation(value = "不分页", notes = "传入materialInfo")
	public R<List<MaterialInfoVO>> rawMaterialList(MaterialInfoVO materialInfo, Query query) {
		List<MaterialInfoVO> pages = materialInfoService.selectRawMaterialList(materialInfo);
		return R.data(pages);
	}

	/**
	 * 分页 材料信息（材料库）
	 */
	@GetMapping("/pagelist")
	//@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入materialInfo")
	public R<IPage<MaterialInfo>> pageList(MaterialInfo materialInfo, Query query) {
		IPage<MaterialInfo> pages = materialInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(materialInfo));
		return R.data(pages);
	}

	/**
	 * 自定义分页 材料信息（材料库）
	 */
	@GetMapping("/page")
	//@ApiOperationSupport(order = 3)
	@ApiOperation(value = "分页", notes = "传入materialInfo")
	public R<IPage<MaterialInfoVO>> page(MaterialInfoVO materialInfo, Query query) {
		IPage<MaterialInfoVO> pages = materialInfoService.selectMaterialInfoPage(Condition.getPage(query), materialInfo);
		return R.data(pages);
	}

	@GetMapping("/fisMaterialList")
	//@ApiOperationSupport(order = 3)
	@ApiOperation(value = "分页", notes = "传入materialInfo")
	public R<List<MaterialInfoVO>> fisMaterialList(MaterialInfoVO materialInfo) {
		return R.data(materialInfoService.fisMaterialList(materialInfo));
	}

	/**
	 * 新增 材料信息（材料库）
	 */
	@PostMapping("/save")
	//@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入materialInfo")
	public R save(@Valid @RequestBody MaterialInfo materialInfo) {
		try {
			QueryWrapper queryWrapper = new QueryWrapper<MaterialInfo>().eq("material_no", materialInfo.getMaterialNo());
//		.eq("material_name", materialInfo.getMaterialName())
//				.eq("specifications",materialInfo.getSpecifications()).eq("model",materialInfo.getModel()).eq("tenant_id", AuthUtil.getTenantId());
			long count = materialInfoService.count(queryWrapper);
			if (count > 0) {
				return R.fail("该零件编码已存在，请重新编辑！");
			}
			//条码前缀重复
//		long count2 = materialInfoService.count(new QueryWrapper<MaterialInfo>().lambda().eq(MaterialInfo::getLabelCodePrefix, materialInfo.getLabelCodePrefix()));
//		if(count2>0){
//			return R.fail("该零件标签条码前缀已存在!");
//		}
			/****2023-01-16 任务5210 编码手动填写***/
			boolean flag = materialInfoService.save(materialInfo);

			/**异步向物流推送材料信息-新增 start**/
//		if(flag){
//			ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
//			PrdAndMaterialInfoSyncThread thread = new PrdAndMaterialInfoSyncThread(1,1,null,materialInfo,null);
//			cachedThreadPool.execute(thread);
//		}
			/**异步向物流推送材料信息-新增 end**/
			return R.status(flag);
		} finally {
			OpcUaCache.clear();
		}
	}

	/**
	 * 修改 材料信息（材料库）
	 */
	@PostMapping("/update")
	//@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入materialInfo")
	public R update(@Valid @RequestBody MaterialInfo materialInfo) {
		try {
			QueryWrapper queryWrapper = new QueryWrapper<MaterialInfo>().ne("id", materialInfo.getId())
				.eq("material_no", materialInfo.getMaterialNo());
//				.eq("material_name", materialInfo.getMaterialName()).eq("specifications",materialInfo.getSpecifications())
//				.eq("model",materialInfo.getModel()).eq("tenant_id",AuthUtil.getTenantId());
			long count = materialInfoService.count(queryWrapper);
			if (count > 0) {
				return R.fail("该零件编码已存在，请重新编辑！");
			}
//		MaterialInfo old = materialInfoService.getById(materialInfo.getId());
//		if(!materialInfo.getLabelCodePrefix().equals(old.getLabelCodePrefix())){
//			//条码前缀重复
//			long count2 = materialInfoService.count(new QueryWrapper<MaterialInfo>().lambda().eq(MaterialInfo::getLabelCodePrefix, materialInfo.getLabelCodePrefix()));
//			if(count2>0){
//				return R.fail("该零件标签条码前缀已存在!");
//			}
//		}
			/****2023-01-16 任务5210 编码手动填写***/
//		MaterialInfo oldMaterial = materialInfoService.getById(materialInfo.getId());
//		if (!oldMaterial.getMaterialGroupNo().equals(materialInfo.getMaterialGroupNo())){
//		}
			boolean flag = materialInfoService.updateById(materialInfo);
			/**异步向物流推送材料信息-修改 start**/
//		if(flag){
//			ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
//			PrdAndMaterialInfoSyncThread thread = new PrdAndMaterialInfoSyncThread(1,2,null,materialInfo,null);
//			cachedThreadPool.execute(thread);
//		}
			/**异步向物流推送材料信息-修改 end**/
			return R.status(flag);
		} finally {
			OpcUaCache.clear();
		}
	}

//	/**
//	 * 新增或修改 材料信息（材料库）
//	 */
//	@PostMapping("/submit")
//	//@ApiOperationSupport(order = 6)
//	@ApiOperation(value = "新增或修改", notes = "传入materialInfo")
//	public R submit(@Valid @RequestBody MaterialInfo materialInfo) {
//		QueryWrapper queryWrapper = new QueryWrapper<MaterialInfo>().ne("id", materialInfo.getId())
//				.and(wapper -> wapper.eq("material_no", materialInfo.getMaterialNo()).
//						or().eq("material_grade", materialInfo.getMaterialGrade()).
//						or().eq("material_name", materialInfo.getMaterialName()));
//		int count = materialInfoService.count(queryWrapper);
//		if(count > 0){
//			return R.fail("材料编码或牌号或名称重复，请重新编辑！");
//		}
//		return R.status(materialInfoService.saveOrUpdate(materialInfo));
//	}


	/**
	 * 删除 材料信息（材料库）
	 */
	@PostMapping("/remove")
	//@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		try {
			List<MaterialInfo> materialInfoList = materialInfoService.list(new QueryWrapper<MaterialInfo>().in("id", Func.toLongList(ids)));
			List<String> materialNos = materialInfoList.stream().map(mat -> mat.getMaterialNo()).collect(Collectors.toList());
			//根据材料牌号判断材料是否在BOM中被引用
			for (String materialNo : materialNos) {
				List<PrdBom> bomList = prdBomService.list(new QueryWrapper<PrdBom>().eq("material_no", materialNo));
				if (CollectionUtil.isNotEmpty(bomList)) {
					List<String> bomNoList = bomList.stream().map(PrdBom::getDirectLeaderNo).distinct().collect(Collectors.toList());
					String join = String.join(",", bomNoList);
					String msg = String.format("零件:%s,被Bom引用,不能删除.Bom:%s", materialNo, join);
					return R.fail(msg);
				}
			}
			boolean flag = materialInfoService.deleteLogic(Func.toLongList(ids));
//		if(flag){
//			/**异步向物流推送材料信息-删除 start**/
//			ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
//			PrdAndMaterialInfoSyncThread thread = new PrdAndMaterialInfoSyncThread(1,3,null,null,Func.toLongList(ids));
//			cachedThreadPool.execute(thread);
//		}
			/**异步向物流推送材料信息-删除 end**/
			return R.status(flag);
		} finally {
			OpcUaCache.clear();
		}
	}

	/**
	 * 获取产品/物料信息
	 */
	@GetMapping("/getMaterialInfo")
	@ApiOperation(value = "获取产品/物料信息")
	public R getMaterialInfo(MaterialInfoVO materialInfo) {
		return materialInfoService.getMaterialInfo(materialInfo);
	}

	/**
	 * 获取产品/物料信息(质量用)
	 */
	@GetMapping("/getMaterialInfoByQuality")
	@ApiOperation(value = "获取产品/物料信息(质量用)")
	public R getMaterialInfoBy(MaterialInfoVO materialInfo) {
		return materialInfoService.getMaterialInfoByQuality(materialInfo);
	}

	/**
	 * 获取巡检规则零件(质量用)
	 */
	@PostMapping("/getMaterialInfoByPatrol")
	@ApiOperation(value = "获取巡检规则零件(质量用)")
	public R<List<MaterialInfo>> getMaterialInfoByPatrol(@RequestBody MaterialInfoVO materialInfo) {
		return materialInfoService.getMaterialInfoByPatrol(materialInfo);
	}

	/**
	 * 获取原材料和辅助材料的牌号
	 */
	@GetMapping("/getMaterialInfos")
	@ApiOperation(value = "获取原材料和辅助材料的牌号/物料信息")
	public R getMaterialInfos() {
		List<MaterialInfo> materialInfoList = materialInfoService.getMaterialInfos();
		return R.data(materialInfoList);
	}


	/**
	 * 质量获取物流数据page接口
	 */
	@GetMapping("/getQuaMaterialInfoPage")
	//@ApiOperationSupport(order = 8)
	@ApiOperation(value = "质量获取物流数据page接口", notes = "传入materialInfo")
	public R<IPage<MaterialInfoVO>> getQuaMaterialInfoPage(MaterialInfoVO materialInfo, Query query) {
		IPage<MaterialInfoVO> pages = materialInfoService.getQuaMaterialInfoPage(Condition.getPage(query), materialInfo);
		return R.data(pages);
	}

//	@GetMapping("/downloadFile")
//	//@ApiOperationSupport(order = 9)
//	@ApiOperation(value = "下载模板")
//	public void downloadFile(HttpServletRequest request, HttpServletResponse response){
//		ExcelUtil.importTempDownLoad(request, response, "材料信息导入模板", "材料信息");
//	}
//	@PostMapping("/uploadMaterialInfo")
//	//@ApiOperationSupport(order = 10)
//	@ApiOperation(value = "导入材料信息", notes = "传入file，materialType")
//	public R uploadMaterialInfo(@RequestParam(value = "file") MultipartFile file) throws IOException {
//		//检查文件类型
//		Boolean flag = ExcelUtil.checkFile(file);
//		if(!flag){
//			return R.fail("文件类型不正确");
//		}
//		Map<String,Object> map = ExcelUtil.analysisFile(file);
//		return materialInfoService.importMaterialInfo(map);
//	}

	@GetMapping("/exportMaterialInfo")
	//@ApiOperationSupport(order = 10)
	@ApiOperation(value = "导出材料信息", notes = "equipmentInfo，ids")
	public void exportMaterialInfo(HttpServletRequest request, HttpServletResponse response, MaterialInfoVO materialInfo, String ids) {
		materialInfoService.exportMaterialInfo(request, response, materialInfo, ids);
	}

	/**
	 * 通过idList获取所有物料
	 */
	@GetMapping("/materialListByIdList")
	@ApiOperation(value = "通过idList获取所有物料", notes = "传入list")
	public R<List<MaterialInfo>> materialListByIdList(@RequestParam List<Long> longList) {
		List<MaterialInfo> materialInfos = materialInfoService.materialListByIdList(longList);
		return R.data(materialInfos);
	}

	/**
	 * 通过materialNoList获取所有物料
	 */
	@PostMapping("/materialListByNoList")
	@ApiOperation(value = "通过materialNoList获取所有物料", notes = "传入list")
	public R<List<MaterialInfo>> materialListByNoList(@RequestBody List<String> materialNoList) {
		List<MaterialInfo> materialInfos = materialInfoService.materialListByNoList(materialNoList);
		return R.data(materialInfos);
	}

	@PostMapping("/updatePackaging")
	@ApiOperation(value = "修改是否有包装方案", notes = "传入materialInfo")
	public R updatePackaging(@Valid @RequestBody MaterialInfo materialInfo) {
		return R.status(materialInfoService.updateById(materialInfo));
	}

	/**
	 * 导出
	 *
	 * @param ids 参数值
	 * @author yewang
	 * @since 2023-03-14
	 */
	@GetMapping("/derive")
	//@ApiOperationSupport(order = 3)
	@ApiOperation(value = "导出", notes = "传入id")
	public void deriveMaterial(HttpServletRequest request, HttpServletResponse response, MaterialInfoVO materialInfo, String ids) {
		materialInfo.setMaterialFlags(Func.toStrList(materialInfo.getMaterialFlag()));
		materialInfo.setMaterialTypes(Func.toStrList(materialInfo.getMaterialType()));
		materialInfoService.deriveMaterial(materialInfo, ids, request, response);
	}

	@GetMapping("/getTree")
	//@ApiOperationSupport(order = 7)
	@ApiOperation(value = "字典树", notes = "传入code,dictKey")
	public R<List<DictTreeNode>> getTree(String code, String dictKey) {
		return R.data(materialInfoService.getTree(code, dictKey));
	}
}
